home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.mactech.com 2010
/
ftp.mactech.com.tar
/
ftp.mactech.com
/
machack
/
Hacks97
/
BillBoot.sit
/
Bill Boot
/
source code
/
BillBoot.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-06-27
|
29KB
|
1,170 lines
/*
File: WinBoot.c
Contains: Hack to make the Mac boot sequence resemble
a PC/Win95 boot sequence.
Written by: Eric Traut
Date: 6/25/97
*/
#include <OSUtils.h>
#include <Events.h>
#include <Menus.h>
#include <Quickdraw.h>
#include <Dialogs.h>
#include <TextEdit.h>
#include <Devices.h>
#include <Windows.h>
#include <Fonts.h>
#include <LowMem.h>
#include <Gestalt.h>
#include <Palettes.h>
#include <Retrace.h>
#include <Sound.h>
#include <MixedMode.h>
#include <Traps.h>
#include <Processes.h>
#include <QDOffscreen.h>
/* Static and Global Variables */
static GDHandle sMainDevice;
static UInt16 sBitsPerPixel;
static Rect sRealDeviceRect;
static Rect sDeviceRect;
static Ptr sRealDeviceBasePtr;
static Ptr sDeviceBasePtr;
static UInt32 sDeviceRowBytes;
static UInt16 sTotalTextColumns;
static UInt16 sTotalTextRows;
static UInt16 sCurTextRow = 0;
static Handle sWin95SplashScreen = NULL;
static Handle sWin95Colors = NULL;
static Handle sPCFont = NULL;
static Handle sWin95BootSound = NULL;
static UInt32 sNextStateChangeTicks;
static UInt32 sCurrentDrawState;
static UInt32 sCurrentDrawSubState;
static UInt32 sMachineSpeed;
static UInt32 sMachineMemory;
static UInt32 sMachineType;
static VBLTask sVBLTask;
static QDGlobals myQd;
static UniversalProcPtr sOriginalLaunch;
static UniversalProcPtr sOriginalDMB;
static UniversalProcPtr sOriginalSetEntries;
static SInt16 sPictWidth;
static SInt16 sPictHeight;
static SInt16 sHScale;
static SInt16 sVScale;
static Boolean sLaunchPatchActive = true;
static Boolean sDMBPatchActive = true;
static Boolean sSetEntriesPatchActive = true;
static Boolean sVBLRunning = true;
static UInt32 sLastInitName = 0;
static SndChannelPtr sSoundChannel = NULL;
/* Local Functions */
static void InitMac(void);
static void InstallVBL(void);
static Boolean InitScreenInfo(void);
static void LoadResources(void);
static void ApplyPatches(void);
static void InstallVBL(void);
static void DrawWin95SplashScreen(void);
static void DrawWin95ProgressBar(UInt8 inCurStage);
static void DrawDOSText(UInt16 inHPos, UInt16 inVPos, StringPtr inString, Boolean inInvert);
static void VBLDrawProc(VBLTaskPtr vblTaskPtr);
static Boolean DoMemoryTest(void);
static void TearDownHacks(void);
static void PlayWin95StartSound(void);
static void GetProcessorString(Str255 outProcString);
static void AppendPString(StringPtr ioStrA, StringPtr ioStrB);
pascal OSErr LaunchPatchProc(LaunchPBPtr LaunchParams);
pascal void DMBPatchProc(void);
pascal void SetEntriesPatch(short start, short count, CSpecArray aTable);
static Boolean HasNewInitName(Str63 outInitName);
static void DrawNewInitName(Str63 inInitName);
static void ScrollTextScreen(UInt16 inRows);
static void DoBillGatesAnimation(void);
/* Static Routine Descriptors */
static RoutineDescriptor sVBLRD = BUILD_ROUTINE_DESCRIPTOR(uppVBLProcInfo, &VBLDrawProc);
static RoutineDescriptor sLaunchRD = BUILD_ROUTINE_DESCRIPTOR(kPascalStackBased | RESULT_SIZE(kTwoByteCode) | STACK_ROUTINE_PARAMETER(1, kFourByteCode), &LaunchPatchProc);
static RoutineDescriptor sDMBRD = BUILD_ROUTINE_DESCRIPTOR(kPascalStackBased, &DMBPatchProc);
static RoutineDescriptor sSetEntriesRD = BUILD_ROUTINE_DESCRIPTOR(kPascalStackBased | STACK_ROUTINE_PARAMETER(1, kTwoByteCode) | STACK_ROUTINE_PARAMETER(2, kTwoByteCode) | STACK_ROUTINE_PARAMETER(3, kFourByteCode), &SetEntriesPatch);
/* Constant Definitions */
enum
{
kTextCellHSize = 8,
kTextCellVSize = 16,
// Drawing states
kDrawBIOSMessage = 0,
kDrawMemorySize,
kDrawStartingOS,
kDrawCDDriverText,
kMouseDriverText,
kBlinkCursor,
kDrawWin95Screen,
kAnimateWin95Screen,
kProgressBarHeight = 26,
kBillScrollAmount = 8
};
/*--------------------------------------------------------
main
Main entry point to the INIT.
--------------------------------------------------------*/
void
main(void)
{
// We need to initialize the Mac toolbox first
InitMac();
// Next we'll blank the entire screen to prepare to
// make it look like a PC screen at boot time
if (InitScreenInfo())
{
// Next, we'll load our resource (fonts, PICTs, etc.
// so they are in memory when we need them).
LoadResources();
// We need to temporarily patch out calls to QuickDraw
// so icons and other items in the boot sequence are
// not drawn on top of us.
ApplyPatches();
// Initialize our state
sCurrentDrawState = kDrawBIOSMessage;
sNextStateChangeTicks = 0;
// Finally, we'll install a VBL task to complete
// our boot sequence.
InstallVBL();
//TearDownHacks();
}
}
/*--------------------------------------------------------
InitMac
Initializes the Mac toolbox.
--------------------------------------------------------*/
void
InitMac(void)
{
long gestaltResult;
OSErr tempErr;
// Get information about the CPU (type and speed)
tempErr = Gestalt(gestaltNativeCPUtype, &gestaltResult);
if (tempErr == noErr)
sMachineType = gestaltResult;
else
sMachineType = 0;
tempErr = Gestalt('pclk', &gestaltResult);
if (tempErr == noErr)
sMachineSpeed = gestaltResult;
else
sMachineSpeed = 0;
// Get information about memory (size of memory in Kb)
(void) Gestalt(gestaltPhysicalRAMSize, &gestaltResult);
sMachineMemory = gestaltResult / 1024L;
InitGraf(&myQd.thePort);
}
/*--------------------------------------------------------
InitScreenInfo
Determines the bounds of the main monitor and its
bit depth. If the depth is in the range we support,
it blanks the screen and returns true. Else it returns
false to indicate the INIT should just quietly do
nothing.
--------------------------------------------------------*/
Boolean
InitScreenInfo(void)
{
PixMapHandle devicePixMap;
sMainDevice = GetMainDevice();
if (sMainDevice == NULL)
return false;
devicePixMap = (**sMainDevice).gdPMap;
if (devicePixMap == NULL)
return false;
// We currently only handle 8-bit for now
sBitsPerPixel = (**devicePixMap).pixelSize;
if (sBitsPerPixel != 8)
return false;
// Stash away some information about the device
sDeviceRect = sRealDeviceRect = (**devicePixMap).bounds;
// We don't support less than 640x480
if (sDeviceRect.right - sDeviceRect.left < 640 || sDeviceRect.bottom - sDeviceRect.top < 480)
return false;
sDeviceBasePtr = sRealDeviceBasePtr = (**devicePixMap).baseAddr;
sDeviceRowBytes = (**devicePixMap).rowBytes & 0x3FFF;
// Hide the cursor so we don't draw over it
HideCursor();
return true;
}
/*--------------------------------------------------------
LoadResources
Loads our resources into the system heap, then locks
them down so they don't move in the heap. We need to
be able to access these resources from interrupt time.
--------------------------------------------------------*/
void
LoadResources(void)
{
SInt16 scrnWidth;
SInt16 scrnHeight;
scrnWidth = sDeviceRect.right - sDeviceRect.left;
scrnHeight = sDeviceRect.bottom - sDeviceRect.top;
// Make common screen sizes fit our constraints
if (scrnWidth >= 3 * 320 && scrnHeight >= 2 * 384)
{
sHScale = 3;
sVScale = 2;
sPictWidth = sHScale * 320;
sPictHeight = sVScale * 384;
sWin95SplashScreen = Get1Resource('SCRN', 128);
}
else if (scrnWidth >= 400 * 2 && scrnHeight >= 2 * 300)
{
sHScale = 2;
sVScale = 2;
sPictWidth = sHScale * 400;
sPictHeight = sVScale * 300;
sWin95SplashScreen = Get1Resource('SCRN', 129);
}
else
{
sHScale = 2;
sVScale = 2;
sPictWidth = sHScale * 320;
sPictHeight = sVScale * 240;
sWin95SplashScreen = Get1Resource('SCRN', 130);
}
// Adjust the device rect
sDeviceRect.left += (scrnWidth - sPictWidth) / 2;
sDeviceRect.right -= (scrnWidth - sPictWidth) / 2;
sDeviceRect.top += (scrnHeight - sPictHeight) / 2;
sDeviceRect.bottom -= (scrnHeight - sPictHeight) / 2;
sDeviceBasePtr += (scrnWidth - sPictWidth) / 2 +
(scrnHeight - sPictHeight) * sDeviceRowBytes;
if (sWin95SplashScreen == NULL)
DebugStr("\pCouldn't load splash screen");
sTotalTextColumns = (sDeviceRect.right - sDeviceRect.left) / kTextCellHSize;
sTotalTextRows = (sDeviceRect.bottom - sDeviceRect.top) / kTextCellVSize;
sWin95Colors = Get1Resource('SPLT', 128);
if (sWin95Colors == NULL)
DebugStr("\pCouldn't load color palette");
sPCFont = Get1Resource('Font', 128);
if (sPCFont == NULL)
DebugStr("\pCouldn't load font bitmap");
sWin95BootSound = Get1Resource('snd ', 128);
if (sWin95BootSound == NULL)
DebugStr("\pCouldn't load boot sound");
DetachResource(sWin95SplashScreen);
MoveHHi(sWin95SplashScreen);
HLock(sWin95SplashScreen);
DetachResource(sWin95Colors);
MoveHHi(sWin95Colors);
HLock(sWin95Colors);
DetachResource(sPCFont);
MoveHHi(sPCFont);
HLock(sPCFont);
DetachResource(sWin95BootSound);
MoveHHi(sWin95BootSound);
HLock(sWin95BootSound);
DoBillGatesAnimation();
if (sWin95Colors != NULL)
{
// Set up our palette for correct colors
SetGDevice(sMainDevice);
// Turn our patch off momentarily so it takes effect
SetEntries(0, 255, (ColorSpec*)*sWin95Colors);
}
}
/*--------------------------------------------------------
ApplyPatches
We need to prevent other INITs from drawing to the
screen (that would spoil the effect).
--------------------------------------------------------*/
void
ApplyPatches(void)
{
PixMapHandle devicePixMap;
devicePixMap = (**sMainDevice).gdPMap;
if (devicePixMap == NULL)
return;
// Point the base address of the main device
// to ROM so pixels are dropped in the bit bucket.
// Leave some slop to work around QD bugs.
(**devicePixMap).baseAddr = LMGetROMBase() + 1024;
sOriginalLaunch = GetToolTrapAddress(_Launch);
SetToolTrapAddress(&sLaunchRD, _Launch);
sOriginalDMB = GetToolTrapAddress(_DrawMenuBar);
SetToolTrapAddress(&sDMBRD, _DrawMenuBar);
sOriginalSetEntries = GetToolTrapAddress(_SetEntries);
SetToolTrapAddress(&sSetEntriesRD, _SetEntries);
}
/*--------------------------------------------------------
InstallVBL
Installs a VBL task we use to drive the animation
throughout the boot process.
--------------------------------------------------------*/
void
InstallVBL(void)
{
sVBLTask.qLink = NULL;
sVBLTask.qType = vType;
sVBLTask.vblAddr = &sVBLRD;
sVBLTask.vblCount = 1;
sVBLTask.vblPhase = 0;
VInstall((QElemPtr)&sVBLTask);
}
/*--------------------------------------------------------
DrawWin95SplashScreen
Draws the Win95 splash screen directly to the main
device.
--------------------------------------------------------*/
void
DrawWin95SplashScreen(void)
{
UInt8* curSrcPixel;
UInt8* curDestRow;
UInt8* curDestPixel;
UInt16 curRow;
UInt16 curCol;
if (sWin95SplashScreen == NULL)
return;
curSrcPixel = (UInt8*)*sWin95SplashScreen;
curDestPixel = curDestRow = (UInt8*)sDeviceBasePtr;
for (curRow = 0; curRow < sPictHeight - kProgressBarHeight; curRow += sVScale)
{
for (curCol = 0; curCol < sPictWidth; curCol += sHScale)
{
UInt16 pixel;
pixel = *curSrcPixel++;
if (sHScale == 3)
{
// Pixel double in vertical direction, pixel triple in horizontal
curDestPixel[0] = pixel;
curDestPixel[1] = pixel;
curDestPixel[2] = pixel;
curDestPixel[0 + sDeviceRowBytes] = pixel;
curDestPixel[1 + sDeviceRowBytes] = pixel;
curDestPixel[2 + sDeviceRowBytes] = pixel;
}
else
{
// Pixel double in vertical direction, pixel double in horizontal
curDestPixel[0] = pixel;
curDestPixel[1] = pixel;
curDestPixel[0 + sDeviceRowBytes] = pixel;
curDestPixel[1 + sDeviceRowBytes] = pixel;
}
curDestPixel += sHScale;
}
curDestRow += sDeviceRowBytes * sVScale;
curDestPixel = curDestRow;
}
}
/*--------------------------------------------------------
DrawWin95ProgressBar
Draws the Win95 progress bar on the bottom of the
screen.
--------------------------------------------------------*/
void
DrawWin95ProgressBar(UInt8 inCurStage)
{
UInt8* curDestRow;
UInt8* curDestPixel;
UInt16 curRow;
UInt16 curCol;
curDestPixel = curDestRow = (UInt8*)sDeviceBasePtr +
sDeviceRowBytes * (sPictHeight - kProgressBarHeight);
for (curRow = sPictHeight - kProgressBarHeight; curRow < sPictHeight; curRow++)
{
for (curCol = 0; curCol < sPictWidth; curCol += 4)
{
UInt32 pixel;
// Determine which color index to use. Our color
// ramp is 0xF7 to 0xFD.
pixel = (curCol / (sPictWidth / 16)) + inCurStage;
if (pixel > 15)
pixel -= 16;
if (pixel > 7)
pixel = 15 - pixel;
pixel += 0xF7;
pixel = (pixel << 24) + (pixel << 16) + (pixel << 8) + pixel;
*(UInt32*)curDestPixel = pixel;
curDestPixel += 4;
}
curDestRow += sDeviceRowBytes;
curDestPixel = curDestRow;
}
}
/*--------------------------------------------------------
DrawDOSText
Draws the specified text at the h/v coordinate using
DOS characters. The coordinate is in text coordinates,
so 0,0 is the top, left-most cell on the screen.
--------------------------------------------------------*/
void
DrawDOSText(UInt16 inHPos, UInt16 inVPos, StringPtr inString, Boolean inInvert)
{
UInt16 curCharIndex;
UInt8* curSrcRow;
UInt8* curSrcPixel;
UInt8* curDestRow;
UInt8* curDestPixel;
UInt16 curRow;
UInt16 curCol;
UInt8 curChar;
UInt8 invertMask;
// Multiply by the cell size (accounting for pixel doubling)
inHPos *= kTextCellHSize;
inVPos *= kTextCellVSize;
invertMask = inInvert ? 0xFF : 0x00;
for (curCharIndex = 0; curCharIndex < inString[0]; curCharIndex++)
{
curChar = inString[curCharIndex + 1];
// Determine source pointer to font graphic data
curSrcPixel = curSrcRow = (curChar - '!') * kTextCellHSize + (UInt8*)*sPCFont;
// Determine destination location in video buffer
curDestPixel = curDestRow = (UInt8*)sDeviceBasePtr +
sDeviceRowBytes * (UInt32)inVPos + inHPos;
// We only have graphic information for characters in this range
if (curChar == ' ' || (curChar >= '!' && curChar <= '~'))
{
for (curRow = 0; curRow < kTextCellVSize; curRow++)
{
if (curChar == ' ')
{
// For a space, clear the entire box
for (curCol = 0; curCol < kTextCellHSize; curCol++)
*curDestPixel++ = (0xFF ^ invertMask);
}
else
{
for (curCol = 0; curCol < kTextCellHSize; curCol++)
*curDestPixel++ = (-*curSrcPixel++) ^ invertMask;
}
curDestRow += sDeviceRowBytes;
curDestPixel = curDestRow;
curSrcRow += ('~' - '!' + 1) * kTextCellHSize;
curSrcPixel = curSrcRow;
}
}
inHPos += kTextCellHSize;
}
}
/*--------------------------------------------------------
VBLDrawProc
This is the VBL procedure that determines which state
we're in currently and calls the correct drawing
routine.
--------------------------------------------------------*/
void
VBLDrawProc(VBLTaskPtr vblTaskPtr)
{
#pragma unused (vblTaskPtr)
UInt32 curTicks;
Str255 processorString;
Str63 newInitName;
char initChar;
curTicks = LMGetTicks();
if (curTicks >= sNextStateChangeTicks)
{
switch (sCurrentDrawState)
{
case kDrawBIOSMessage:
// Draw the BIOS text
DrawDOSText(1, sCurTextRow, "\pMacOS Toolbox BIOS", false);
DrawDOSText(sTotalTextColumns - 34, sCurTextRow++,
"\p(C) Apple Computer, Inc. 1984-97", false);
GetProcessorString(processorString);
DrawDOSText(1, sCurTextRow, processorString, false);
// Progress to the next state after several ticks
sNextStateChangeTicks = curTicks + 10;
sCurrentDrawState = kDrawMemorySize;
sCurrentDrawSubState = 0;
break;
case kDrawMemorySize:
if (DoMemoryTest())
{
// Progress to the next state after several ticks
sCurrentDrawState = kDrawStartingOS;
sNextStateChangeTicks = curTicks + 60;
}
else
{
// If we are not done testing memory, keep
// going in this state for a while
sNextStateChangeTicks = curTicks + 2;
}
break;
case kDrawStartingOS:
sCurTextRow += 6;
DrawDOSText(1, sCurTextRow, "\pStarting MacOS 8.0...", false);
// Progress to the next state almost immediately
sCurrentDrawState = kDrawCDDriverText;
sNextStateChangeTicks = curTicks + 20;
sCurrentDrawSubState = 15;
sCurTextRow += 2;
break;
case kDrawCDDriverText:
DrawDOSText(1, sCurTextRow, "\pApple CD-ROM Driver, Version 8.0 (SCSI001)", false);
DrawDOSText(1, sCurTextRow + 1, "\pLooking for CD-ROM Drive", (sCurrentDrawSubState & 0x1) == 0);
if (--sCurrentDrawSubState == 0)
{
// Progress to the next state after a while
DrawDOSText(1, sCurTextRow + 1, "\pCD-ROM Drive Detected ", false);
sCurrentDrawState = kMouseDriverText;
sCurTextRow += 3;
}
else
{
sNextStateChangeTicks = curTicks + 20;
}
break;
case kMouseDriverText:
DrawDOSText(1, sCurTextRow++, "\pMacOS Mouse Driver 8.0", false);
DrawDOSText(1, sCurTextRow++, "\pCopyright (C) Apple Computer, Inc. 1984-97", false);
DrawDOSText(1, sCurTextRow++, "\pStandard ADB Mouse Detected", false);
sCurTextRow++;
sCurrentDrawState = kBlinkCursor;
sNextStateChangeTicks = curTicks + 30;
sCurrentDrawSubState = 50000;
break;
case kBlinkCursor:
// Has a new INIT been loaded since last time?
if (HasNewInitName(newInitName))
{
DrawDOSText(1, sCurTextRow, "\p ", false);
DrawNewInitName(newInitName);
if (sCurTextRow > sTotalTextRows - 4)
ScrollTextScreen(2);
else
sCurTextRow += 2;
// This is really gross, but if the current INIT
// name is beyond the a certain point, we'll continue.
initChar = ((sLastInitName >> 16) & 0xFF);
if (initChar > 'a')
initChar -= 'a' - 'A';
if (initChar > 'S')
sCurrentDrawState = kDrawWin95Screen;
}
// Blink the cursor every 8th time
if ((sCurrentDrawSubState % 8) == 0)
{
if ((sCurrentDrawSubState % 16) == 0)
DrawDOSText(1, sCurTextRow, "\p_", false);
else
DrawDOSText(1, sCurTextRow, "\p ", false);
}
if (--sCurrentDrawSubState == 0)
sCurrentDrawState = kDrawWin95Screen;
break;
case kDrawWin95Screen:
DrawWin95SplashScreen();
// Progress to the next state immediately
sCurrentDrawState = kAnimateWin95Screen;
sCurrentDrawSubState = 0;
break;
case kAnimateWin95Screen:
DrawWin95ProgressBar(sCurrentDrawSubState);
// Keep animating every few ticks
sNextStateChangeTicks = curTicks + 6;
sCurrentDrawSubState++;
if (sCurrentDrawSubState > 15)
sCurrentDrawSubState = 0;
break;
}
}
// Reprime the VBL task so we are called back again
sVBLTask.vblCount = 1;
}
/*--------------------------------------------------------
DoMemoryTest
Draws the memory test text to the DOS screen. Returns
true once the memory test is complete.
--------------------------------------------------------*/
Boolean
DoMemoryTest(void)
{
Str31 memorySizeText;
UInt16 curCharIndex;
UInt32 memorySize;
// Clear out the string
for (curCharIndex = 0; curCharIndex < 10; curCharIndex++)
memorySizeText[curCharIndex] = ' ';
// Construct the memory size string
memorySizeText[9] = 'K';
memorySizeText[0] = 9;
memorySize = sCurrentDrawSubState;
for (curCharIndex = 8; curCharIndex > 0; curCharIndex--)
{
memorySizeText[curCharIndex] = (memorySize % 10) + '0';
memorySize /= 10;
if (memorySize == 0)
break;
}
// Draw the new text
DrawDOSText(1, 4, memorySizeText, false);
// Add one megabyte (1024Kb) to the state
sCurrentDrawSubState += 1024;
// Did we report all the memory?
return (sCurrentDrawSubState > sMachineMemory);
}
/*--------------------------------------------------------
TearDownHacks
Removes the VBL task, patches, etc.
--------------------------------------------------------*/
void
TearDownHacks(void)
{
PixMapHandle devicePixMap;
// Restore the real base address of the main device
devicePixMap = (**sMainDevice).gdPMap;
if (devicePixMap == NULL)
return;
(**devicePixMap).baseAddr = sRealDeviceBasePtr;
VRemove((QElemPtr)&sVBLTask);
RestoreDeviceClut(sMainDevice);
sSetEntriesPatchActive = false;
ShowCursor();
}
/*--------------------------------------------------------
PlayWin95StartSound
Plays the Win95 start wound asynchronously.
--------------------------------------------------------*/
void
PlayWin95StartSound(void)
{
if (sSoundChannel != NULL)
(void) SndPlay(sSoundChannel, (SndListHandle)sWin95BootSound, true);
}
/*--------------------------------------------------------
GetProcessorString
Returns an ASCII string that describes the speed
and type of processor.
--------------------------------------------------------*/
void
GetProcessorString(Str255 outProcString)
{
UInt32 mhz;
outProcString[0] = 3;
outProcString[1] = ' ';
outProcString[2] = ' ';
// Convert speed from Hz to MHz (rounding if necessary)
mhz = (sMachineSpeed + 500000L) / 1000000L;
outProcString[3] = (mhz % 10) + '0';
mhz /= 10;
if (mhz > 0)
outProcString[2] = (mhz % 10) + '0';
mhz /= 10;
if (mhz > 0)
outProcString[1] = (mhz % 10) + '0';
AppendPString(outProcString, "\pMHz ");
switch (sMachineType)
{
case gestaltCPU601:
AppendPString(outProcString, "\pPowerPC 601");
break;
case gestaltCPU603:
AppendPString(outProcString, "\pPowerPC 603");
break;
case gestaltCPU604:
AppendPString(outProcString, "\pPowerPC 604");
break;
case 0x106:
AppendPString(outProcString, "\pPowerPC 603e");
break;
case 0x107:
AppendPString(outProcString, "\pPowerPC 603ev");
break;
case 0x108:
AppendPString(outProcString, "\pPowerPC 740");
break;
case 0x109:
AppendPString(outProcString, "\pPowerPC 604e");
break;
case 0x10A:
AppendPString(outProcString, "\pPowerPC 760");
break;
default:
AppendPString(outProcString, "\pUnknown Processor");
break;
}
}
/*--------------------------------------------------------
AppendPString
Appends one pascal string onto a second.
--------------------------------------------------------*/
void
AppendPString(StringPtr ioStrA, StringPtr ioStrB)
{
UInt16 curStrIndex;
for (curStrIndex = 0; curStrIndex < ioStrB[0]; curStrIndex++)
ioStrA[ioStrA[0] + curStrIndex + 1] = ioStrB[curStrIndex + 1];
ioStrA[0] += ioStrB[0];
}
/*--------------------------------------------------------
LaunchPatchProc
Patch for the _Launch trap.
--------------------------------------------------------*/
pascal OSErr
LaunchPatchProc(LaunchPBPtr launchParams)
{
OSErr tempErr;
// Disable ourselves now
if (sLaunchPatchActive)
{
THz oldZone;
oldZone = GetZone();
SetZone(SystemZone());
// Allocate a sound channel so we can call the start sound
(void) SndNewChannel(&sSoundChannel, squareWaveSynth, 0, NULL);
SetZone(oldZone);
PlayWin95StartSound();
}
sLaunchPatchActive = false;
// Chain through to the caller
tempErr = CallUniversalProc((UniversalProcPtr)sOriginalLaunch,
kPascalStackBased | RESULT_SIZE(kTwoByteCode) | STACK_ROUTINE_PARAMETER(1, kFourByteCode),
launchParams);
return tempErr;
}
/*--------------------------------------------------------
DMBPatchProc
Patch for the _DrawMenuBar trap.
--------------------------------------------------------*/
pascal void
DMBPatchProc(void)
{
// Disable ourselves now
if (!sLaunchPatchActive && sDMBPatchActive)
{
TearDownHacks();
sDMBPatchActive = false;
}
// Chain through to the caller
(void) CallUniversalProc((UniversalProcPtr)sOriginalDMB, kPascalStackBased);
}
/*--------------------------------------------------------
SetEntriesPatch
Prevents the system from taking over the clut while
we're installed
--------------------------------------------------------*/
pascal void
SetEntriesPatch(short start, short count, CSpecArray aTable)
{
if (!sSetEntriesPatchActive)
{
// Call through to original
(void) CallUniversalProc((UniversalProcPtr)sOriginalSetEntries,
kPascalStackBased |
STACK_ROUTINE_PARAMETER(1, kTwoByteCode) |
STACK_ROUTINE_PARAMETER(2, kTwoByteCode) |
STACK_ROUTINE_PARAMETER(3, kFourByteCode),
start,
count,
aTable);
}
}
/*--------------------------------------------------------
HasNewInitName
Determines whether there is a new INIT loading
since the last time we checked. If a new INIT is
being loaded since the last time we were called,
we return true.
--------------------------------------------------------*/
Boolean
HasNewInitName(Str63 outInitName)
{
StringPtr curInitName;
UInt16 curChar;
Boolean initChanged = false;
curInitName = *(StringPtr*)0x914;
// Make sure there is a valid INIT name hanging off of 0x914
if (*(UInt32*)0x910 == 0xFFFFFFFF &&
(UInt32)curInitName != 0xFFFFFFFF &&
((UInt32)curInitName & 0x3) == 0 &&
(SInt32)curInitName > 0)
{
curInitName = *(StringPtr*)0x914;
if (curInitName[0] >= 4 && sLastInitName != *(UInt32*)curInitName)
{
// Copy the current INIT name to our output. Since we're
// being called at interrupt time, it's possible the name
// is only partially copied, but it's most likely intact.
for (curChar = 0; curChar <= curInitName[0]; curChar++)
outInitName[curChar] = curInitName[curChar];
// Record the first four bytes so we can tell when it changes
sLastInitName = *(UInt32*)curInitName;
initChanged = true;
}
}
return initChanged;
}
/*--------------------------------------------------------
DrawNewInitName
Outputs a message at the current line describing
the INIT being loaded.
--------------------------------------------------------*/
void
DrawNewInitName(Str63 inInitName)
{
DrawDOSText(1, sCurTextRow, "\pLoading driver ", false);
DrawDOSText(16, sCurTextRow, inInitName, false);
}
/*--------------------------------------------------------
ScrollTextScreen
Scrolls the entire text buffer up the specified
number of rows.
--------------------------------------------------------*/
void
ScrollTextScreen(UInt16 inRows)
{
UInt32* curSrc;
UInt32* curDest;
UInt32* curSrcRow;
UInt32* curDestRow;
UInt16 curColumn;
UInt16 curRow;
curSrcRow = curSrc = (UInt32*)(sDeviceBasePtr + sDeviceRowBytes * inRows * kTextCellVSize);
curDestRow = curDest = (UInt32*)sDeviceBasePtr;
for (curRow = 0; curRow < sTotalTextRows * kTextCellVSize; curRow++)
{
if (curRow >= (sTotalTextRows - inRows) * kTextCellVSize)
{
// Fill in last few rows with black
for (curColumn = 0; curColumn < sTotalTextColumns * kTextCellHSize; curColumn += 4)
*curDest++ = 0xFFFFFFFF;
}
else
{
for (curColumn = 0; curColumn < sTotalTextColumns * kTextCellHSize; curColumn += 4)
*curDest++ = *curSrc++;
}
curSrcRow = (UInt32*)((UInt8*)curSrcRow + sDeviceRowBytes);
curDestRow = (UInt32*)((UInt8*)curDestRow + sDeviceRowBytes);
curSrc = curSrcRow;
curDest = curDestRow;
}
}
/*--------------------------------------------------------
DoBillGatesAnimation
Scrolls the Mac screen off to the right while Bill
Gates pushes it.
--------------------------------------------------------*/
void
DoBillGatesAnimation(void)
{
GDHandle savedGD;
CGrafPtr savedPort;
CGrafPtr wMgrPort;
Rect curRect;
Rect billRect;
Rect billEraseRect;
UInt32 lastTicks;
RgnHandle dummyRgn;
PicHandle billPict1;
PicHandle billPict2;
PicHandle billPict3;
PicHandle curBillPict;
UInt8 curStage = 0;
UInt32 scrnWidth;
UInt8 bobStep = 0;
billPict1 = GetPicture(128);
billPict2 = GetPicture(129);
billPict3 = GetPicture(130);
curBillPict = billPict1;
billRect = (*billPict1)->picFrame;
OffsetRect(&billRect, -billRect.right, -billRect.bottom + sRealDeviceRect.bottom);
billEraseRect = billRect;
billEraseRect.right = billEraseRect.left;
billEraseRect.left = billEraseRect.right - kBillScrollAmount - 4;
GetGWorld(&savedPort, &savedGD);
GetCWMgrPort(&wMgrPort);
SetGWorld(wMgrPort, sMainDevice);
// Fill in background with black
BackColor(blackColor);
curRect = sRealDeviceRect;
lastTicks = TickCount();
dummyRgn = NewRgn();
scrnWidth = sRealDeviceRect.right - sRealDeviceRect.left;
while (billRect.left < curRect.right)
{
ScrollRect(&curRect, kBillScrollAmount, 0, dummyRgn);
DrawPicture(curBillPict, &billRect);
EraseRect(&billEraseRect);
OffsetRect(&billRect, kBillScrollAmount, bobStep >= 4 ? -2 : 2);
billEraseRect.right += kBillScrollAmount;
curRect.left += kBillScrollAmount;
bobStep++;
if (bobStep >= 8)
bobStep = 0;
// Add a small delay so we don't move too fast
while (TickCount() <= lastTicks + 2) {};
lastTicks = TickCount();
switch (curStage)
{
case 0:
if (curRect.left >= 6 * scrnWidth / 10)
{
curBillPict = billPict2;
curStage++;
}
break;
case 1:
if (curRect.left >= 7 * scrnWidth / 10)
{
curBillPict = billPict3;
curStage++;
}
break;
case 2:
if (curRect.left >= 8 * scrnWidth / 10)
{
curBillPict = billPict2;
curStage++;
}
break;
case 3:
if (curRect.left >= 9 * scrnWidth / 10)
{
curBillPict = billPict1;
curStage++;
}
break;
}
}
EraseRect(&sRealDeviceRect);
DisposeRgn(dummyRgn);
SetGWorld(savedPort, savedGD);
}